package com.usooft.metaTalent.core.system.service.basic;

import com.usooft.metaTalent.core.system.entity.Role;
import com.usooft.metaTalent.core.system.entity.RolePermission;
import com.usooft.metaTalent.core.system.query.RolePermissionQuery;
import com.usooft.metaTalent.core.system.service.RolePermissionService;
import com.usooft.metaTalent.core.system.service.base.BaseRolePermissionService;
import com.usooft.metaTalent.core.system.wrapper.RolePermissionWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class BasicRolePermissionService extends BaseRolePermissionService implements RolePermissionService {

    // region 自动生成
    // endregion

    @Override
    @Cacheable(value = "permissionsByRoleId", key = "#roleId")
    public Set<String> listPermissionsByRoleId(@NonNull Long roleId) {
        Assert.notNull(roleId, "必须提供角色 ID");
        return list(RolePermissionQuery.builder()
                .filter(RolePermissionQuery.Filter.builder()
                        .roleIdIs(roleId)
                        .build())
                .build())
                .stream()
                .map(RolePermission::getPermission)
                .collect(Collectors.toSet());
    }

    @Override
    @Transactional
    @CacheEvict(value = "permissionsByRoleId", key = "#role.id")
    public void grant(@NonNull Role role, String... permissions) {
        Assert.notNull(role, "必须提供角色");

        // 需要设置的权限
        Set<String> activeExpressions = permissions == null
                ? new HashSet<>()
                : new HashSet<>(Arrays.asList(permissions));

        // 当前已存在权限
        List<RolePermissionWrapper> currentRolePermissions = list(RolePermissionQuery.builder()
                .filter(RolePermissionQuery.Filter.builder()
                        .roleIdIs(role.getId())
                        .build())
                .build());
        Set<String> currentExpressions = currentRolePermissions.stream().map(RolePermission::getPermission).collect(Collectors.toSet());

        // 取消权限
        List<RolePermissionWrapper> needRemoved = currentRolePermissions.stream()
                .filter(rp -> !activeExpressions.contains(rp.getPermission()))
                .toList();
        if (!needRemoved.isEmpty()) {
            needRemoved.forEach(this::internalDelete);
            log.info("角色 [{}] 取消权限 [{}]", role.getName(), needRemoved.stream().map(RolePermission::getPermission).collect(Collectors.joining(", ")));
        }

        // 新增权限
        Set<String> needAddedExpressions = activeExpressions.stream()
                .filter(Predicate.not(currentExpressions::contains))
                .collect(Collectors.toSet());
        if (!needAddedExpressions.isEmpty()) {
            for (String expression : needAddedExpressions) {
                internalAdd(role.getId(), expression);
            }
            log.info("角色 [{}] 新增权限 [{}]", role.getName(), String.join(", ", needAddedExpressions));
        }
    }
}